﻿// ----------------------------------------------------------------------
// <author name="Moses Kehengu"/>
// <copyright file="UserInformation.cs" company="Futures Group International">
//     Copyright statement. All right reserved
// </copyright>
//
// ------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using GenericTools;
using ReportingManagement.Classes;
using DataModels.Enumerations;

namespace ReportingManagement
{
    /// <summary>
    /// Registered User Information
    /// </summary>
    public class UserInformation : NotifyingModelBase
    {
        #region Class Variables
        private int id;
        private string userSignature;
        private string username;
        private string password;
        private string _EncryptedPassword;
        private string firstname;
        private string lastname;
        private string emailAddress;
        private string phoneNumber;
        private AccessLevel accessLevel;
        private int accessLevelID;
        private string accessLevelValue;
        private int supportingPartnerId;
        private bool valid;
        #endregion

        #region Constructors
        /// <summary>
        /// Creates invalid user information object
        /// </summary>
        private UserInformation()
        {
            this.id = -1;
            this.userSignature = DataTransformation.Encrypt(id.ToString());
            this.username = String.Empty;
            this.password = String.Empty;
            this.firstname = String.Empty;
            this.lastname = String.Empty;
            this.emailAddress = String.Empty;
            this.phoneNumber = String.Empty;
            this.accessLevelID = -1;
            this.accessLevel = AccessLevel.RESTRICTED;
            this.accessLevelValue = String.Empty;
            this.supportingPartnerId = -1;
            this.valid = false;
        }

        public UserInformation(int id, string username, string encryptedPassword, string firstname, 
            string lastname, string emailAddress, string phoneNumber, string accessLevel, 
            string accessLevelValue, int supportingPartnerId)
        {
            this.id = id;
            this.username = username;
            this._EncryptedPassword = encryptedPassword;
            this.password = DataTransformation.Decrypt(encryptedPassword);
            this.firstname = firstname;
            this.lastname = lastname;
            this.emailAddress = emailAddress;
            this.phoneNumber = phoneNumber;
            this.accessLevelValue = accessLevelValue;
            this.userSignature = DataTransformation.Encrypt(id.ToString());
            this.supportingPartnerId = supportingPartnerId;
            this.valid = false;

            int level = Int32.Parse(accessLevel);
            this.accessLevel = AccessLevel.RESTRICTED;
            if (level == 1) this.accessLevel = AccessLevel.ADMINISTRATOR;
            if (level == 2) this.accessLevel = AccessLevel.NATION;
            if (level == 3) this.accessLevel = AccessLevel.REGION;
            if (level == 4) this.accessLevel = AccessLevel.DISTRICT;
            if (level == 5) this.accessLevel = AccessLevel.FACILITY;
        }

        /// <summary>
        /// Deletes this user from the database
        /// </summary>
        /// <returns>True on success otherwise false</returns>
        public bool Delete(int actionUserId)
        {
            bool success = DeleteUser(id);
            if (success)
            {
                this.id = -1;
                this.username = String.Empty;
                this.password = String.Empty;
                this.firstname = String.Empty;
                this.lastname = String.Empty;
                this.emailAddress = String.Empty;
                this.phoneNumber = String.Empty;
                this.accessLevelID = -1;
                this.accessLevel = AccessLevel.RESTRICTED;
                this.accessLevelValue = String.Empty;
                this.supportingPartnerId = -1;
                this.valid = false;
            }
            return success;
        }
        #endregion

        #region Public Static Methods
        /// <summary>
        /// Creates user information
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns>UserInformation object containing user information</returns>
        public static UserInformation CreateUser(string username)
        {
            DataTable userData = Utilities.GetUserInformation(username);
            UserInformation info = CreateUser(userData);
            return info;
        }

        /// <summary>
        /// Creates user information
        /// </summary>
        /// <param name="username">Username</param>
        /// <param name="password">Password</param>
        /// <returns>UserInformation object containing user information</returns>
        public static UserInformation CreateUser(string username, string password)
        {
            //password = GenericTools.DataTransformation.Hash(password);
            DataTable userData = Utilities.GetUserInformation(username, password);
            UserInformation info = CreateUser(userData);
            return info;
        }

        /// <summary>
        /// Creates user information
        /// </summary>
        /// <param name="id">User Record Unique identifier</param>
        /// <returns>UserInformation object containing user information</returns>
        public static UserInformation CreateUser(int id)
        {
            DataTable userData = Utilities.GetUserInformation(id);
            UserInformation info = CreateUser(userData);
            return info;
        }

        /// <summary>
        /// Insert new user into the database
        /// </summary>
        /// <param name="firstname">First name</param>
        /// <param name="lastname">Last name</param>
        /// <param name="username">Username</param>
        /// <param name="password">Password</param>
        /// <param name="email">E-mail address</param>
        /// <param name="phoneNumber">Phone Number</param>
        /// <param name="accessLevel">Access Level</param>
        /// <param name="accessLevelValue">Access Level Value</param>
        /// <returns>UserInformation object</returns>
        public static UserInformation CreateNewUser(string firstname, string lastname, string username, 
            string password, string email, string phoneNumber, AccessLevel accessLevel, 
            string accessLevelValue, int supportingPartnerId, int actionUserId)
        {
            int accessLevelID = -1;
            if (accessLevel == AccessLevel.ADMINISTRATOR) accessLevelID = 1;
            if (accessLevel == AccessLevel.NATION) accessLevelID = 2;
            if (accessLevel == AccessLevel.REGION) accessLevelID = 3;
            if (accessLevel == AccessLevel.DISTRICT) accessLevelID = 4;
            if (accessLevel == AccessLevel.FACILITY) accessLevelID = 5;

            int id = Utilities.CreateNewUser(firstname, lastname, username, password, email, phoneNumber, 
                accessLevelID, accessLevelValue, supportingPartnerId, actionUserId);
            if (id != -1)
            {
                UserInformation user = new UserInformation();
                user.id = id;
                user.firstname = firstname;
                user.lastname = lastname;
                user.username = username;
                user.password = password;
                user.emailAddress = email;
                user.phoneNumber = phoneNumber;
                user.accessLevel = accessLevel;
                user.accessLevelID = accessLevelID;
                user.accessLevelValue = accessLevelValue;
                user.supportingPartnerId = supportingPartnerId;
                user.valid = true;
                return user;
            }
            else return null;
        }

        /// <summary>
        /// Deletes user from the database
        /// </summary>
        /// <param name="id">Database unique identifier of user</param>
        /// <returns>True on success otherwise false</returns>
        public static bool DeleteUser(int id)
        {
            bool success = false;
            success = Utilities.DeleteUser(id);
            return success;
        }

        public static bool IsUsernameAvailable(string username)
        {
            bool available = false;
            available = Utilities.IsUsernameAvailable(username);
            return available;
        }
        #endregion

        #region Private Helper Methods
        /// <summary>
        /// Create user information
        /// </summary>
        /// <param name="userData">DataTable object containing information about the user about to be created</param>
        /// <returns>UserInformation object containing user information</returns>
        private static UserInformation CreateUser(DataTable userData)
        {
            if (userData.Rows.Count == 1)
            {
                DataRow row = userData.Rows[0];
                UserInformation info = new UserInformation();
                info.id = int.Parse(row["ID"].ToString());
                info.username = row["Username"].ToString();
                info.password = DataTransformation.Decrypt(row["Password"].ToString());
                info.firstname = row["FirstName"].ToString();
                info.lastname = row["LastName"].ToString();
                info.emailAddress = row["EmailAddress"].ToString();
                info.phoneNumber = row["PhoneNumber"].ToString();
                info.accessLevelID = int.Parse(row["AccessLevelID"].ToString());
                info.supportingPartnerId = Int32.Parse(row["SupportingPartnerId"].ToString());

                switch (info.accessLevelID)
                {
                    case 1:
                        info.accessLevel = AccessLevel.ADMINISTRATOR;
                        break;

                    case 2:
                        info.accessLevel = AccessLevel.NATION;
                        break;

                    case 3:
                        info.accessLevel = AccessLevel.REGION;
                        break;

                    case 4:
                        info.accessLevel = AccessLevel.DISTRICT;
                        break;

                    case 5:
                        info.accessLevel = AccessLevel.FACILITY;
                        break;

                    default:
                        info.accessLevel = AccessLevel.RESTRICTED;
                        break;
                }

                info.accessLevelValue = row["AccessLevelValue"].ToString();
                info.userSignature = DataTransformation.Encrypt(info.id.ToString());
                info.valid = true;
                return info;
            }
            else return null;
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Checks whether this object is valid or not
        /// </summary>
        public bool Valid
        {
            get
            {
                return this.valid;
            }
        }

        /// <summary>
        /// Database record unique identifier
        /// </summary>
        public int ID
        {
            get
            {
                return this.id;
            }
        }

        /// <summary>
        /// Encrypted user's unique identifier
        /// </summary>
        public string UserSignature
        {
            get
            {
                return this.userSignature;
            }
        }

        /// <summary>
        /// Username
        /// </summary>
        public string Username
        {
            get
            {
                return this.username;
            }
        }

        /// <summary>
        /// Password
        /// </summary>
        public string Password
        {
            get
            {
                return this.password;
            }
            set
            {
                this.password = value;
                OnPropertyChanged("Password");
            }
        }

        /// <summary>
        /// Encrypted Password
        /// </summary>
        public string EncryptedPassword
        {
            get
            {
                return _EncryptedPassword;
            }
            set
            {
                _EncryptedPassword = value;
                OnPropertyChanged("EncryptedPassword");
            }
        }

        /// <summary>
        /// First name
        /// </summary>
        public string FirstName
        {
            get
            {
                return this.firstname;
            }
            set
            {
                this.firstname = value;
                OnPropertyChanged("FirstName");
            }
        }

        /// <summary>
        /// Last name
        /// </summary>
        public string LastName
        {
            get
            {
                return this.lastname;
            }
            set
            {
                this.lastname = value;
                OnPropertyChanged("LastName");
            }
        }

        /// <summary>
        /// Full name
        /// </summary>
        public string FullName
        {
            get
            {
                string fullname = String.Format("{0} {1}", this.firstname, this.lastname);
                return fullname;
            }
        }

        /// <summary>
        /// E-mail address
        /// </summary>
        public string EmailAddress
        {
            get
            {
                return this.emailAddress;
            }
            set
            {
                this.emailAddress = value;
                OnPropertyChanged("EmailAddress");
            }
        }

        /// <summary>
        /// Phone Number
        /// </summary>
        public string PhoneNumber
        {
            get
            {
                return this.phoneNumber;
            }
            set
            {
                this.phoneNumber = value;
                OnPropertyChanged("PhoneNumber");
            }
        }

        /// <summary>
        /// Gets Access Level
        /// </summary>
        public AccessLevel Level
        {
            get
            {
                return this.accessLevel;
            }
            set
            {
                this.accessLevel = value;
                OnPropertyChanged("Level");
            }
        }

        public string AccessLevelText
        {
            get
            {
                string text = String.Empty;
                switch (this.accessLevel)
                {
                    case AccessLevel.ADMINISTRATOR:
                        text = "Administrator";
                        break;

                    case AccessLevel.NATION:
                        text = "Nation";
                        break;

                    case AccessLevel.REGION:
                        text = "Region";
                        break;

                    case AccessLevel.DISTRICT:
                        text = "District";
                        break;

                    case AccessLevel.FACILITY:
                        text = "Facility";
                        break;
                        
                    case AccessLevel.RESTRICTED:
                        text = "Restricted";
                        break;
                }
                return text;
            }
        }

        /// <summary>
        /// Access Level Value
        /// </summary>
        public string AccessLevelValue
        {
            get
            {
                return this.accessLevelValue;
            }
            set
            {
                this.accessLevelValue = value;
                OnPropertyChanged("AccessLevelValue");
            }
        }

        public int SupportingPartnerId
        {
            get
            {
                return supportingPartnerId;
            }
            set
            {
                supportingPartnerId = value;
                OnPropertyChanged("SupportingPartnerId");
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Changes user password
        /// </summary>
        /// <param name="oldPassword">Old password</param>
        /// <param name="newPassword">New password</param>
        /// <returns>True if the password is changed otherwise false</returns>
        public bool ChangePassword(string oldPassword, string newPassword)
        {
            //string oldPasswordHash = GenericTools.DataTransformation.Hash(oldPassword);
            //string newPasswordHash = GenericTools.DataTransformation.Hash(newPassword);
            //bool okToContinue = Utilities.ChangePassword(this.id, oldPasswordHash, newPasswordHash);
            bool okToContinue = Utilities.ChangePassword(this.id, oldPassword, newPassword);
            if (okToContinue)
            {
                //this.password = newPasswordHash;
                this.password = newPassword;
                return true;
            }
            else return false;
        }

        public bool Save(int actionUserId)
        {
            bool succes = Utilities.UpdateUserDetails(id, firstname, lastname, password, 
                emailAddress, phoneNumber, accessLevel, accessLevelValue, supportingPartnerId, actionUserId);
            return succes;
        }
        #endregion
    }    
}
